/***************************************************************************************************
  *Copyright(C),2010-2017,Sumscope
  *FileName	:  pinyin_search_idfile.h
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2017/06/04
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :  
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/
#pragma once

#include "pinyin_search_define.h"
#include "pinyin_search_key.h"
#include "pinyin_search_idvec.h"
namespace qb{
	namespace base{
		namespace internal{
#define ROUND_ALIGN(NUM, SIZE) ((NUM%SIZE==0)?NUM:((NUM/SIZE+1)*SIZE))
			class IndexIdRange;
#ifdef WIN32
			typedef unsigned __int64 u64;
#else
            typedef unsigned long long u64;
#endif
			class SingleMappingView;
			class MultiMappingView;
			class IndexIdFile {
				enum{
					SIGNATURE = 0xFEFEABCD,
					MEGA_BYTES = 1024 * 1024,
				};
				using MappingView = SingleMappingView;
				struct KeyHead{
					int				m_offset;			// 在映射文件中的偏移量
					int				m_signature;		// SIGNATURE
					int				m_used;				// 已经使用的空间
					int				m_bytes;			// 整块内存大小
					int				m_capcity;			// 预留空间
					int				m_length;			// 个数:24,8	高24位表示bid,低8位表示个数,对应InverseSet的key,value
					wchar_t			m_key[4];			// 
				};
				struct Block{						// 代表空余空间
					int			bytes;
					bool		valid;
				public:
					Block() :bytes(0), valid(false){}
					Block(int b, bool v) :bytes(b), valid(v){}
				};
				class KeyHeadMemory{
                    typedef std::map<void*, KeyHead*> BackupMemory;
                    typedef std::map<int, KeyHead*> OffsetMap;
					BackupMemory	m_memory;					// 备份内存
					OffsetMap		m_offsets;
				public:
					KeyHeadMemory(){}
					~KeyHeadMemory();
					int GetSize()const{ return m_memory.size(); }
					bool IsEmpty()const{ return m_memory.empty(); }
					bool Free(void* memory, int offset, int bytes);
					KeyHead* GetHead(int offset, int bytes);
					KeyHead* AllocHead(int offset,int bytes);
					int GetMemoryBytes()const;
				};

				int				m_align_size;				// 每个KeyHad对应数据占据内存的大小对齐值,大小必须是此数字的整数倍
				float			m_reserve_ratio;			// 预留比例
				int				m_increase_size;			// 文件每次变大递增的尺寸,默认32mb
				int				m_sys_pagesize;				// 系统的页面大小,分配内存即按照此对齐

				int				m_cur_filesize;				// 当前映射文件大小,通常是m_increase_size的整数倍
				int				m_cur_usedsize;				// 已经使用的大小
#ifdef WIN32
                void*			m_file;						// 文件句柄
#else
                int             m_file;						// 文件句柄
#endif
                void*			m_mapping;					// 映射文件句柄
				MappingView*	m_view;						// 映射文件区域,随机映射区域
                std::map<int, Block> m_blocks;					//
				KeyHeadMemory	m_keyheads;					// 备份内存,优先级高
                std::string		m_fname;					// 文件名称
			public:
				IndexIdFile(int npageCount=4);
				~IndexIdFile();
			protected:
				bool Initialize(const char* fname);
				bool PrepareMapping(int maxSize);
			protected:
				void* AllocSpace(int bytes, int& offset);
				void FreeSpace(void* memory, int offset, int bytes);
				KeyHead* PrepareSpace(int offset, int bytes);
				void* AllocByMapping(int bytes);
			public:
				void Dump()const;
				int  GetMemoryBytes()const;
				void Update(const InverseKey& key, IndexIdRange* iirange);
				bool AddKey(IndexIdRange* iirange, int key);
				bool RemoveKey(IndexIdRange* iirange, int key);
				bool GetIndexIdVec(const IndexIdRange* iirange, IndexIdVec& iivec);
			};

		}
	}
}
